package com.dcivision.dms.web;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.dcivision.alert.bean.UpdateAlert;
import com.dcivision.alert.core.AdapterMaster;
import com.dcivision.alert.core.AlertManager;
import com.dcivision.audit.AuditTrailConstant;
import com.dcivision.audit.core.AuditTrailManager;
import com.dcivision.dms.DmsErrorConstant;
import com.dcivision.dms.DmsOperationConstant;
import com.dcivision.dms.bean.DmsContent;
import com.dcivision.dms.bean.DmsDocument;
import com.dcivision.dms.bean.DmsVersion;
import com.dcivision.dms.bean.MtmDocumentRelationship;
import com.dcivision.dms.core.DmsContentManager;
import com.dcivision.dms.core.DocumentRetrievalManager;
import com.dcivision.dms.core.FileDownloader;
import com.dcivision.dms.dao.MtmDocumentRelationshipDAObject;
import com.dcivision.framework.AdapterMasterFactory;
import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.DataSourceFactory;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.HTTPUtility;
import com.dcivision.framework.MessageResourcesFactory;
import com.dcivision.framework.PermissionManager;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.Utility;
import com.dcivision.framework.web.WebUtil;

public class FileDownloadServlet extends HttpServlet {
  private static final Log log = LogFactory.getLog(FileDownloadServlet.class);
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	SessionContainer sessionContainer = (SessionContainer)request.getSession().getAttribute(GlobalConstant.SESSION_CONTAINER_KEY);

  if(Utility.isEmpty(sessionContainer)){
		  response.sendRedirect(request.getContextPath()+"/dms/MaintDmsDocument.do?documentType="+request.getParameter("documentType")+"&ID="+request.getParameter("targetID")+"&sCurFunctionCode="+request.getParameter("sCurFunctionCode")+"&navMode="+GlobalConstant.NAV_MODE_PREVIEW);
		  return;
	}
	
    if(!Utility.isEmpty(request.getParameter("xlsModule"))&& request.getParameter("xlsModule").equals("FolderStructureImportTemplate.xls")){
    	openFolderStructureImportTemplate(sessionContainer,request,response);
    	return;
    }
    
    // Retrieval Document ID and its Version ID
    Integer targetID = TextUtility.parseIntegerObj(request.getParameter("targetID"));
    String version = request.getParameter("version");
    String curFunctionCode = request.getParameter("sCurFunctionCode");
    Integer versionID = new Integer (1);
    String documentType = request.getParameter("documentType");
    String invite = request.getParameter("invitation");
    boolean isDownload = "Y".equals(request.getParameter("isDownload"));

    //Retrieval System Log and UpdateAlert info
    Integer updateAlertSystemLogID = TextUtility.parseIntegerObj(request.getParameter("updateAlertSystemLogID"));
    if (updateAlertSystemLogID==null) {
      updateAlertSystemLogID = TextUtility.parseIntegerObj(request.getParameter("systemLogID"));
    }
    boolean invitationOverwrite = SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_INVITATION_OVERWRITE_STANDARD);
    String systemLogID = request.getParameter("systemLogID");

    String permission = "";
    boolean readPhyiscalFileError = false;
    
    InputStream dataStream = null;
    Connection conn = null;

    try {
      conn = DataSourceFactory.getConnection();
      PermissionManager permissionManager = sessionContainer.getPermissionManager();
      DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
      MtmDocumentRelationshipDAObject docRelationshipDAO = new MtmDocumentRelationshipDAObject(sessionContainer, conn);
      DmsContentManager dmsContentManager = new DmsContentManager(sessionContainer, conn);      
      AlertManager alertManager = new AlertManager(sessionContainer, conn);

      if (DmsDocument.DOCUMENT_LINK.equals(documentType)) {
        targetID= docRelationshipDAO.getTargetDocIDByRelatedDocID(TextUtility.parseIntegerObj(request.getParameter("targetID")),documentType);
      }
      String errorMessage = null;
      boolean hasInvitation = false;
      boolean hasPermission = permissionManager.hasAccessRight(conn, GlobalConstant.OBJECT_TYPE_DOCUMENT, targetID, "R");
      if (!hasPermission) {
      	if(!Utility.isEmpty(invite)){
      	  hasInvitation = true;
      	}
      }
      
      if (!hasPermission && !hasInvitation) {
        this.notAllowToRead(sessionContainer, request, response, errorMessage);
      }else {
        
        if (!Utility.isEmpty(systemLogID)) {
          alertManager.updateReadOperationLog(TextUtility.parseIntegerObj(systemLogID));
        }
  
        DmsDocument document = docRetrievalManager.getDocument(targetID);
  
        DmsVersion dmsVersion = new DmsVersion();
        Integer contentID = new Integer(0);
        if (!Utility.isEmpty(version) && !DmsOperationConstant.DMS_TOP_VERSION.equals(version)) {
          versionID = TextUtility.parseIntegerObj(version);
          dmsVersion = docRetrievalManager.getVersionByVersionID(versionID);
          contentID = dmsVersion.getContentID();
        } else if (DmsOperationConstant.DMS_TOP_VERSION.equals(version)) {
          dmsVersion = docRetrievalManager.getTopVersionByDocumentID(targetID);
          contentID = dmsVersion.getContentID();
        }
  
        // check login and document access right (**REMIND: document access right is not implemented yet)
        try {
          sessionContainer.getPermissionManager().isAccessible(GlobalConstant.OBJECT_TYPE_DOCUMENT, targetID);
        } catch (ApplicationException appEx) {
          if (ErrorConstant.LOGIN_SESSION_EXPIRED.equals(appEx.getMsgCode())) {
            String redirectURL = request.getContextPath() + "/dms/MaintDmsDocument.do?documentType=" + document.getDocumentType() + "&rootID=" + document.getRootID() + "&parentID="
                             + document.getID() + "&sCurFunctionCode=" + curFunctionCode + "&navMode=" + GlobalConstant.NAV_MODE_PREVIEW + "&ID=" + document.getID() + "&objectID=" + document.getID() + "' ";
            response.sendRedirect(redirectURL);
          }
        }
  
        AdapterMaster am = AdapterMasterFactory.getAdapterMaster(sessionContainer, conn);
        DmsDocument parentDoc = docRetrievalManager.getDocument(document.getParentID());
        permission = sessionContainer.getPermissionManager().getPermission(conn,GlobalConstant.OBJECT_TYPE_DOCUMENT, document.getID());
        try {
          am.call(UpdateAlert.DOCUMENT_TYPE, document.getID(), UpdateAlert.VIEW_ACTION, document.getDocumentName(), null, null, null );
          am.call(UpdateAlert.DOCUMENT_TYPE, parentDoc.getID(), UpdateAlert.VIEW_ACTION, document.getDocumentName(), null, null, null, document.getID() );
          if (docRetrievalManager.hasRelationship(document.getID(),null)) {
            List relationList=docRelationshipDAO.getListByIDRelationType(document.getID(),null);
            List inRelationList=docRelationshipDAO.getListByRelationIDRelationType(document.getID(),null);
            List alertList = new ArrayList();
            if (!Utility.isEmpty(relationList)) {
              for (int i=0;i<relationList.size();i++) {
                alertList = alertManager.listUpdateAlertByObjectTypeObjectIDAndAction(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)relationList.get(i)).getDocumentID(),UpdateAlert.MODIFY_RELATED_DOC);
                if (!Utility.isEmpty(alertList)) {
                  am.call(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)relationList.get(i)).getDocumentID(),UpdateAlert.MODIFY_RELATED_DOC,document.getDocumentName(),
                    null,null,null,document.getID());
                }
              }
            }
            if (!Utility.isEmpty(inRelationList)) {
              for (int i=0;i<inRelationList.size();i++) {
              alertList= alertManager.listUpdateAlertByObjectTypeObjectIDAndAction(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)inRelationList.get(i)).getRelatedDocumentID(),UpdateAlert.MODIFY_RELATED_DOC);
                if(!Utility.isEmpty(alertList)){
                  am.call(UpdateAlert.DOCUMENT_TYPE,((MtmDocumentRelationship)inRelationList.get(i)).getRelatedDocumentID(),UpdateAlert.MODIFY_RELATED_DOC,document.getDocumentName(),
                    null,null,null,document.getID());
                }
              }
            }
          }
        } catch (Exception e) {
          log.error(e.getMessage(), e);
        }
  
        // log down in audit trail
        AuditTrailManager auditManager = new AuditTrailManager(sessionContainer, conn);
        if (sessionContainer.getUserRecordID()!=null && (!DmsDocument.TIF_ANNOTATION_TYPE.equals(document.getDocumentType()))) {
          auditManager.auditTrail(GlobalConstant.OBJECT_TYPE_DOCUMENT, document, AuditTrailConstant.ACCESS_TYPE_VIEW, dmsVersion.getVersionNumber());
        }
        conn.commit();
  
        /* Check for document link download */
        DmsDocument targetDoc = null;
        if (DmsDocument.DOCUMENT_LINK.equals(document.getDocumentType())){
          Integer targetDocID = docRelationshipDAO.getTargetDocIDByRelatedDocID(document.getID(), document.getDocumentType());
          targetDoc = docRetrievalManager.getDocument(targetDocID);
          permission = sessionContainer.getPermissionManager().getPermission(conn,GlobalConstant.OBJECT_TYPE_DOCUMENT, targetDoc.getID());
  
          /* Used to update the doc link name and type; Wont infulence the getDocumentProfileInfo() */
          if (targetDoc!=null) {
            targetDoc.setDocumentName(document.getDocumentName());
            targetDoc.setDocumentType(document.getDocumentType());
            //update the doc ID for shortcut linkage
            targetID = targetDocID;
            document = targetDoc;
  
            //update the real link document version
            dmsVersion = docRetrievalManager.getTopVersionByDocumentID(targetID);
            contentID = dmsVersion.getContentID();
          } else {
            document.setRecordStatus(GlobalConstant.RECORD_STATUS_INACTIVE);
          }
        }
        /*End the Document link download handling */
  
        //Check for deleted document and return the error message on JSP
        String docName = "";
        if ((!GlobalConstant.RECORD_STATUS_INACTIVE.equals(document.getRecordStatus()) && permission.indexOf("R")>=0) || invitationOverwrite ) {
          document.setCurFunctionCode(curFunctionCode);
          docName = document.getDocumentName();
          if(docName.lastIndexOf(".")>0){
        	  docName = docName.substring(0,docName.lastIndexOf(".")+1);
          }
          
          DmsContent docContent = docRetrievalManager.getContentByContentID(contentID);
          if (!Utility.isEmpty(docContent.getExt())) {
            docName = docName + docContent.getExt().toLowerCase();
          }
          docName = this.getFittedFileName(docName); 
          
          docName = TextUtility.getURLEncodeInUTF8(docName);
          
          try{
            dataStream = dmsContentManager.readDmsDocumentStoreContent(document,docContent);            
          }catch(Exception e){
            log.error(e.getMessage(), e);
            readPhyiscalFileError= true;
          }
          
          String contentType=HTTPUtility.getContentType(docName,docContent.getContentType());
          //if have charset value set the charset to response
          if(!Utility.isEmpty(request.getParameter("charset"))){
            response.setContentType("text/html;charset="+request.getParameter("charset"));
          }else{
            response.setContentType("text/html;charset=UTF-8");
          }
          
          if(!readPhyiscalFileError){
            FileDownloader fd = new FileDownloader();
            fd.setFileName(docName);
            fd.setContentType(contentType);
            fd.setIsDownload(isDownload);
            fd.setInputStream(dataStream);
            fd.setRequest(request);
            fd.setResponse(response);
            fd.operate();
          }else{
            printPhysicalFileReadError(sessionContainer,request,response,isDownload);
          }
        } else if (permission.indexOf("R")<0) {
          //Output the error message for no permission
          PrintWriter out = response.getWriter();
          out.println("<script language=\"javascript\">");
          out.println("function callReferrer(url){");
          out.println("    if (url ==''){history.back();}else{ ");
          out.println("    window.location.href = url;} ");
          out.println("    return false; ");
          out.println("}");
          out.println("</script>");
  
          out.println("<table cellpadding=\"20\" cellspacing=\"0\" border=\"0\" width=\"100%\"><tr><td>");
          out.println("<!-- Error Messages -->");
          out.println("<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\"><tr><td>");
          out.println("<UL TYPE=\"square\" style=\"color:#FF0000;font-weight:bold\">");
          out.println("<LI> " + MessageResourcesFactory.getMessage(sessionContainer.getSessionLocale(), "errors.dms.have_no_permissionon_target_file"));
          out.println("</LI></UL>");
          out.println("</td></tr><tr><td>");
          if (isDownload) {
            out.println("<a href=\"#\" onClick=\"return callReferrer(document.referrer);\"><img src=\""+WebUtil.getImage(request, "ButtonBack.gif", false)+"\" align=\"absmiddle\" border=\"0\"></a>");
          } else {
            out.println("<a href=\"javascript:window.close();\"><img src=\""+WebUtil.getImage(request, "ButtonClose.gif", false)+"\" align=\"absmiddle\" border=\"0\"></a>");
          }
          out.println("</td></tr></table>");
        } else {
          //Output the error message for record not found
          PrintWriter out = response.getWriter();
          out.println("<script language=\"javascript\">");
          out.println("function callReferrer(url){");
          out.println("    if (url ==''){history.back();}else{ ");
          out.println("    window.location.href = url;} ");
          out.println("    return false; ");
          out.println("}");
          out.println("</script>");
  
          out.println("<table cellpadding=\"20\" cellspacing=\"0\" border=\"0\" width=\"100%\"><tr><td>");
          out.println("<!-- Error Messages -->");
          out.println("<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\"><tr><td>");
          out.println("<UL TYPE=\"square\" style=\"color:#FF0000;font-weight:bold\">");
          out.println("<LI> " + MessageResourcesFactory.getMessage(sessionContainer.getSessionLocale(), "errors.framework.file_is_deleted"));
          out.println("</LI></UL>");
          out.println("</td></tr><tr><td>");
          if (isDownload) {
            out.println("<a href=\"#\" onClick=\"return callReferrer(document.referrer);\"><img src=\""+WebUtil.getImage(request, "ButtonBack.gif", false)+"\" align=\"absmiddle\" border=\"0\"></a>");
          } else {
            out.println("<a href=\"javascript:window.close();\"><img src=\""+WebUtil.getImage(request, "ButtonClose.gif", false)+"\" align=\"absmiddle\" border=\"0\"></a>");
          }
          out.println("</td></tr></table>");
        }
      }
    } catch (Exception e) {
      log.error(e.getMessage(), e);
    } finally {
      try { dataStream.close(); } catch (Exception ignore) {} finally { dataStream = null; }
      try { conn.close(); } catch (Exception ignore) {} finally { conn = null; }
    }
  }
  
  /**
   * Download filename length can not be more than 159 en char or 17 cn char, so cut the filename when it is long.
   * Add on 07/01/24 for bug EIP-1481. LEE.LV
   * @param zipFileName
   * @return
   * @throws ApplicationException
   */
  private String getFittedFileName(String fileName) {
    String tmpFileName = null;
    String tmpFileExt = null;
    
    int position = fileName.lastIndexOf(".");
    if (position>0) {
      tmpFileName = fileName.substring(0, position);
      tmpFileExt = fileName.substring(position);
    }else {
      tmpFileName = fileName;
      tmpFileExt = "";
    }
    int counter = 0;
    int maxlength = 150;
    for (int i=0; i<tmpFileName.length(); i++) {
      int chAsii = tmpFileName.charAt(i);
      if (chAsii<=0 || chAsii>=126) {
        counter += 9;
      }else {
        counter ++;
      }
      if (counter >= maxlength) {
        tmpFileName = tmpFileName.substring(0, i);
        break;
      }
    }
      
    return tmpFileName + tmpFileExt;
  }
  
  /**
   * joan.xiong add code for bug EIP-264 to download file.2006/09/29
   * @param sessionContainer
   * @param request
   * @param response
   * @throws ServletException
   * @throws IOException
   */
  private void openFolderStructureImportTemplate(SessionContainer sessionContainer,HttpServletRequest request, HttpServletResponse response) throws  IOException {
	  try{
		  String contentType = URLConnection.guessContentTypeFromName(request.getParameter("xlsModule"));
		  String requestURL = request.getRequestURL().toString();
		  String xlsPath = requestURL.substring(0,requestURL.indexOf(request.getContextPath()))+request.getContextPath()+"/jsp/dms/FolderStructureImportTemplate.xls";
		  InputStream dataStream = new URL(xlsPath).openConnection().getInputStream();
		  
		  FileDownloader fd = new FileDownloader();
      fd.setFileName(request.getParameter("xlsModule"));
      fd.setContentType(contentType);
      fd.setIsDownload(true);
      fd.setInputStream(dataStream);
      fd.setRequest(request);
      fd.setResponse(response);
      fd.operate();
    } catch (Exception e) {
      this.printPhysicalFileReadError(sessionContainer, request, response, true);
    }
  }

  private void printPhysicalFileReadError(SessionContainer sessionContainer, HttpServletRequest request, HttpServletResponse response, boolean isDownload)throws IOException {
    //Output the error message for no permission
    PrintWriter out = response.getWriter();
    out.println("<script language=\"javascript\">");
    out.println("function callReferrer(url){");
    out.println("    if (url ==''){history.back();}else{ ");
    out.println("    window.location.href = url;} ");
    out.println("    return false; ");
    out.println("}");
    out.println("</script>");

    out.println("<table cellpadding=\"20\" cellspacing=\"0\" border=\"0\" width=\"100%\"><tr><td>");
    out.println("<!-- Error Messages -->");
    out.println("<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\"><tr><td>");
    out.println("<UL TYPE=\"square\" style=\"color:#FF0000;font-weight:bold\">");
    out.println("<LI> " + MessageResourcesFactory.getMessage(sessionContainer.getSessionLocale(), DmsErrorConstant.PHYSICAL_FILE_NOT_FOUND));
    out.println("</LI></UL>");
    out.println("</td></tr><tr><td>");
    if (isDownload) {
      out.println("<a href=\"#\" onClick=\"return callReferrer(document.referrer);\"><img src=\""+WebUtil.getImage(request, "ButtonBack.gif", false)+"\" align=\"absmiddle\" border=\"0\"></a>");
    } else {
      out.println("<a href=\"javascript:window.close();\"><img src=\""+WebUtil.getImage(request, "ButtonClose.gif", false)+"\" align=\"absmiddle\" border=\"0\"></a>");
    }
    out.println("</td></tr></table>");
  }
  
  private void notAllowToRead(SessionContainer sessionContainer, HttpServletRequest request, HttpServletResponse response, String errorMessage)throws ServletException, IOException {
    //Output the error message for no permission
    PrintWriter out = response.getWriter();
    out.println("<table cellpadding=\"20\" cellspacing=\"0\" border=\"0\" width=\"100%\"><tr><td>");
    out.println("<!-- Error Messages -->");
    out.println("<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\"><tr><td>");
    out.println("<UL TYPE=\"square\" style=\"color:#FF0000;font-weight:bold\">");
    out.println("<LI> " + errorMessage);
    out.println("</LI></UL>");
    out.println("</td></tr><tr><td align=\"center\">");
    out.println("<a href=\"javascript:window.close();\"><img src=\""+WebUtil.getImage(request, "ButtonClose.gif", false)+"\" align=\"absmiddle\" border=\"0\"></a>");
    out.println("</td></tr></table>");
  }
}

